package squarePackage;





import static org.junit.Assert.*;

import java.math.BigDecimal;

import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;

import Enumerations.Directions;
import Enumerations.Slippery;
import Enumerations.Temperature;
import Exceptions.IllegalHeatDamageOverflowException;
import Exceptions.IllegalHumidityException;
import Exceptions.IllegalMinMaxTemperatureException;
import Exceptions.IllegalTemperatureException;
import Obstacle.Door;
import Obstacle.Wall;


/**
 * @version 24/3/2011 20.42
 * @author Pieter & An
 *
 */
public class SquareImpTest {

	/**
	 * @throws java.lang.Exception
	 */
	@BeforeClass
	public static void setUpBeforeClass() throws Exception {
	}

	/**
	 * @throws java.lang.Exception
	 */
	@AfterClass
	public static void tearDownAfterClass() throws Exception {
	}

	/**
	 * @throws java.lang.Exception
	 */
	@Before
	public void setUp() throws Exception {
		newSquare = new PlainSquare(200, new BigDecimal ("0.200"),null);
		mergeSquare =  new PlainSquare(200, new BigDecimal ("0.60"),null);
		
	}

	/**
	 * @throws java.lang.Exception
	 */
	@After
	public void tearDown() throws Exception {
	}

	public Square newSquare;
	public Square mergeSquare;
	
	
	@Test
	public final void firstConstructorLegal(){
		Square otherSquare = new PlainSquare(50,new BigDecimal ("0.20"),null);
		assertEquals(50, otherSquare.getTemperature(),0);
	}
	
	@Test	(expected = IllegalTemperatureException.class)
	public final void firstConstructorIllegalTemperature(){
		Square otherSquare = new PlainSquare(6000000, new BigDecimal("0.50"),null);
	}
	
	@Test
	public final void firstConstructorLegalHumidity(){
		Square otherSquare = new PlainSquare(50,new BigDecimal ("0.20"),null);
		assertEquals(new BigDecimal("0.200"), newSquare.getHumidity());
	}
	
	@Test    (expected = IllegalHumidityException.class)
	public final void firstConstructorIlleLegalHumidity(){
		Square otherSquare = new PlainSquare(50,new BigDecimal ("2.20"),null);
		
	}
	
	@Test 
	public final void secondConstructor(){
		Square otherSquare = new PlainSquare();
		assertEquals(0, otherSquare.getTemperature(),0);
		assertEquals(new BigDecimal("0.50"),otherSquare.getHumidity());	
	}
	
	@Test (expected = IllegalTemperatureException.class)
	public final void setTemperatureMinus400(){
		newSquare.setTemperature(-400,Temperature.CELCIUS);	
	}
	
	@Test (expected = IllegalTemperatureException.class)
	public final void setTemperature400000(){
		newSquare.setTemperature(400000,Temperature.CELCIUS);	
	}	
	
		@Test 
	public final void setTemperature200(){
		newSquare.setTemperature(200,Temperature.CELCIUS);
		assertEquals(200, newSquare.getTemperature(),0);		
	}
	
	@Test
	public final void convertTemperatureFahrenHeit(){
		assertEquals(93.333333333333333, Temperature.convertTemperature(200,Temperature.FAHRENHEIT),0);
	}
	
	@Test
	public final void convertTemperatureKelvin(){
		Temperature.convertTemperature(200,Temperature.KELVIN);
		assertEquals(-73, Temperature.convertTemperature(200,Temperature.KELVIN),0);
	}
	
	@Test
	public final void convertTemperatureCelcius(){
		Temperature.convertTemperature(200,Temperature.CELCIUS);
		assertEquals(200, newSquare.getTemperature(),0);
	}
	
	@Test	(expected = IllegalArgumentException.class)
	public final void convertTemperatureNull(){
		Temperature.convertTemperature(200,null);
	}
	
	@Test
	public final void setTemperatureLegalCase(){
		newSquare.setTemperature(20,Temperature.CELCIUS);
		assertEquals(20, newSquare.getTemperature(),0);
	}
	
	@Test	(expected = IllegalTemperatureException.class)
	public final void setTemperatureIllegalCase(){
		newSquare.setTemperature(60000,Temperature.CELCIUS);
	}
	
	@Test	(expected = IllegalArgumentException.class)
	public final void setTemperatureIllegalCaseNull(){
		newSquare.setTemperature(60000,null);
	}
	
	
	@Test
	public final void isValidTemperatureTrueCase(){
		assertTrue(newSquare.isValidTemperature(100));
	}
	
	@Test
	public final void isValidTemperatureFalseCase6000(){
		assertFalse(newSquare.isValidTemperature(6000));
	}
	
	@Test
	public final void isValidTemperatureFalseCaseMinus6000(){
		assertFalse(newSquare.isValidTemperature(-6000));
	}
	
	@Test
	public final void isValidHumidityLegalcase(){
		assertTrue(newSquare.isValidHumidity(new BigDecimal("0.0")));
	}
	
	@Test
	public final void isValidHumidityIllegalcase(){
		assertFalse(newSquare.isValidHumidity(new BigDecimal("150.0")));
	}
	
	@Test
	public final void isValidHumiditySecondIllegalcase(){
		assertFalse(newSquare.isValidHumidity(new BigDecimal("-150.0")));
	}	
	
	@Test
	public final void isValidMinMaxTemperatureTrueCase(){
		assertTrue(newSquare.isValidMinMaxTemperature(-200.0, 100.0));
	}
	
	@Test
	public final void isValidMinMaxTemperatureTrueCaseEqualMinAndMax(){
		assertTrue(newSquare.isValidMinMaxTemperature(-200.0, 200.0));
	}
	
	@Test
	public final void isValidMinMaxTemperatureFalseCase(){
		assertFalse(newSquare.isValidMinMaxTemperature(200.0, -200.0));
	}	
	
	@Test
	public final void setMinMaxTemperatureTrueCase() throws Exception{
		newSquare.setMinMaxTemperature(-200.0, 100.0);
		assertEquals(-200, newSquare.getMIN_TEMPERATURE(), 0);
		assertEquals(100.0, newSquare.getMAX_TEMPERATURE(),0);
	}
	
	@Test
	public final void setMinMaxTemperatureTrueCaseEqualT() throws Exception{
			newSquare.setMinMaxTemperature(-200.0, -200.0);
			assertEquals(-200, newSquare.getMIN_TEMPERATURE(), 0);
			assertEquals(-200, newSquare.getMAX_TEMPERATURE(),0);
	}
	
	@Test (expected = IllegalMinMaxTemperatureException.class)
	public final void setMinMaxTemperatureFalseCase() throws Exception{
			newSquare.setMinMaxTemperature(-200.0, -300.0);		
	}
	
	@Test
	public final void ColdDamageValueBorderCase(){
		newSquare.setTemperature(-14,Temperature.CELCIUS);
		assertEquals(0, newSquare.coldDamage(), 0);	
	}
	
	@Test
	public final void ColdDamageforTMINUS200(){
		newSquare.setTemperature(-200,Temperature.CELCIUS);
		assertEquals(19, newSquare.coldDamage(), 0);	
	}
	
	@Test
	public final void ColdDamageforPlus200(){
		newSquare.setTemperature(200,Temperature.CELCIUS);
		assertEquals(0, newSquare.coldDamage(), 0);
	}
	
	@Test
	public final void HeatDamageValueBorderCase(){
		newSquare.setTemperature(49,Temperature.CELCIUS);
		assertEquals(0, newSquare.heatDamage(), 0);	
	}
	
	@Test
	public final void HeatDamageforTMINUS200(){
		newSquare.setTemperature(-200,Temperature.CELCIUS);
		assertEquals(0, newSquare.heatDamage(), 0);	
	}
	
	@Test
	public final void HeatDamageforPlus200(){
		newSquare.setTemperature(200,Temperature.CELCIUS);
		newSquare.setHumidity(new BigDecimal("0.10"));
		assertEquals(11, newSquare.heatDamage(), 0);
	}
	
	@Test
	public final void RustDamagefor10perc(){
		newSquare.setHumidity(new BigDecimal("0.1"));
		assertEquals(0, newSquare.rustDamage(), 0);
	}
	
	@Test
	public final void RustDamagefor50perc(){
		newSquare.setHumidity(new BigDecimal("0.5"));
		assertEquals(2, newSquare.rustDamage(), 0);
	}
	
	@Test
	public final void RustDamagefor36perc(){
		newSquare.setHumidity(new BigDecimal("0.36"));
		assertEquals(0, newSquare.rustDamage(), 0);	
	}

	@Test 	(expected =IllegalTemperatureException.class)
	public final void setHeatDamageParametersIllegalTemperatureForLimit(){
		newSquare.setHeatDamageParameters(-3000,50 );
	}
	
	@Test	(expected = IllegalArgumentException.class)
	public final void setHeatDamageParametersIllegalTemeperatureForAmount(){
		newSquare.setHeatDamageParameters(200, -10);
	}
	
	@Test	(expected = IllegalArgumentException.class)
	public final void setHeatDamageParametersIllegalTemeperatureForAmountTooBig(){
		newSquare.setHeatDamageParameters(200, 6000);
	}
	
	@Test
	public final void setHeatDamageParametersLegalCase(){
		newSquare.setHeatDamageParameters(100, 50);
		assertEquals(100, newSquare.getHEAT_DAMAGE_LIMIT(), 0);
		assertEquals(50, newSquare.getHEAT_DAMAGE_AMOUNT(), 0);	
	}
	
	//no black box test are worked out to check conditions that violate preconditions
	@Test
	public final void setRustDamageParameters(){
		newSquare.setRustDamageParameters(new BigDecimal("20"),new BigDecimal("27"));
		assertEquals(new BigDecimal("20"),newSquare.getRUST_DAMAGE_LIMIT());
		assertEquals(new BigDecimal("27"),newSquare.getRUST_DAMAGE_AMOUNT());	
	}
	
	@Test
	public final void setHumidityLegalCase(){
		newSquare.setHumidity(new BigDecimal("0.05"));
		assertEquals(new BigDecimal("0.05"), newSquare.getHumidity());
	}
		
	public final void setSlipperyFIRST(){
		Square anotherSquare = new PlainSquare(10,new BigDecimal("20"),null);
		assertEquals(Slippery.SLIPPERY_MATERIAL, anotherSquare.getSlippery());
		}	
		
		@Test
		public final void setSlipperySECOND(){
			Square anotherSquare = new PlainSquare(100,new BigDecimal("1"),null);
			anotherSquare.setMaterial(false);
			anotherSquare.setSlippery();
			assertEquals(Slippery.WATER_SLIPPERYNESS, anotherSquare.getSlippery());
		}
		
		@Test
		public final void setSlipperyTHIRD(){
			Square anotherSquare = new PlainSquare(0,new BigDecimal("0.20"),null);
			anotherSquare.setMaterial(false);
			anotherSquare.setSlippery();
			assertEquals(Slippery.ICE_LAYER, anotherSquare.getSlippery());
		}
		
		
		@Test
		public final void setSlipperyLAST(){
			Square anotherSquare = new PlainSquare(10,new BigDecimal("0.05"),null);
			anotherSquare.setMaterial(false);
			anotherSquare.setSlippery();
			assertEquals(Slippery.NOT_SLIPPERY, anotherSquare.getSlippery());
		}
	
	@Test
	public final void setBorderEast(){
		newSquare.setBorder(Directions.East,new Wall());
		assertEquals(true, newSquare.hasBorder(Directions.East));
		assertEquals(2, newSquare.hasNumberBorders());
	}
	
	@Test
	public final void setBorderNull(){
		newSquare.setBorder(null,new Wall());
		assertEquals(1, newSquare.hasNumberBorders());
	}

	
	@Test
	public final void setBordersNES(){
		newSquare.setBorder(Directions.North,new Wall());
		newSquare.setBorder(Directions.East,new Wall());
		newSquare.setBorder(Directions.South,new Wall());
		assertEquals(true, newSquare.hasBorder(Directions.East));
		assertEquals(4, newSquare.hasNumberBorders());
	}
	
	@Test
	public final void setBorderToMuch(){
		newSquare.setBorder(Directions.Ceiling,new Wall());
		newSquare.setBorder(Directions.North,new Wall());
		newSquare.setBorder(Directions.East,new Wall());
		newSquare.setBorder(Directions.South,new Wall());
		newSquare.setBorder(Directions.West,new Wall());
		newSquare.setBorder(Directions.Floor,new Wall());
		newSquare.setBorder(Directions.Ceiling,new Wall());
		assertEquals(6, newSquare.hasNumberBorders());
	}
	
	@Test
	public final void setBordersDoubble(){
		newSquare.setBorder(Directions.Ceiling,new Wall());
		newSquare.setBorder(Directions.Ceiling,new Wall());
		newSquare.setBorder(Directions.East,new Wall());
		assertEquals(true, newSquare.hasBorder(Directions.Ceiling));
		assertEquals(3, newSquare.hasNumberBorders());
	}
	
	@Test
	public final void deleteBorder4(){
		newSquare.setBorder(Directions.North,new Wall());
		newSquare.setBorder(Directions.Ceiling,new Wall());
		newSquare.deleteBorder(Directions.North);
		assertEquals(2, newSquare.hasNumberBorders());
		assertFalse(newSquare.hasBorder(Directions.North));
	}
	
	@Test
	public final void deleteBorders(){
		newSquare.setBorder(Directions.Ceiling,new Wall());
		newSquare.setBorder(Directions.North,new Wall());
		newSquare.setBorder(Directions.South ,new Wall());
		newSquare.setBorder(Directions.West,new Wall());
		newSquare.deleteBorder(Directions.South);
		newSquare.deleteBorder(Directions.North);
		assertEquals(3, newSquare.hasNumberBorders());
	}
	
	@Test
	public final void deleteTooManyBorders(){
		newSquare.setBorder(Directions.Floor,new Wall());
		newSquare.deleteBorder(Directions.Floor);
		assertEquals(1, newSquare.hasNumberBorders());
		assertTrue(newSquare.hasBorder(Directions.Floor));
	}
	
	@Test
	public final void calculateNewTemperature85(){
		newSquare.setTemperature(50,Temperature.CELCIUS);
		newSquare.setHumidity(new BigDecimal("0.20"));
		newSquare.setBorder(Directions.East,new Wall());
		mergeSquare.setTemperature(100,Temperature.CELCIUS);
		mergeSquare.setHumidity(new BigDecimal("0.60"));
		mergeSquare.setBorder(Directions.East, new Wall());
		newSquare.mergeWith(mergeSquare, Directions.East);
		assertEquals(85, newSquare.getTemperature(),0);
	}
	
	@Test
	public final void calculateNewTotalTemperature85(){
		newSquare.setTemperature(50,Temperature.CELCIUS);
		newSquare.setHumidity(new BigDecimal("0.20"));
		mergeSquare.setTemperature(100,Temperature.CELCIUS);
		mergeSquare.setHumidity(new BigDecimal("0.60"));
		Square[] squares = {newSquare, mergeSquare};
		newSquare.mergesWith(squares);
		assertEquals(85, newSquare.getTemperature(),0);
	}
	
	@SuppressWarnings("deprecation")
	@Test
	public final void calculateWeights28(){
		BigDecimal[] weights = {new BigDecimal("0.7818"), new BigDecimal("1.2180")};
		assertEquals(weights, newSquare.calculateWeights(new BigDecimal("0.40"),new BigDecimal("0.70")));
	}
	
	@SuppressWarnings("deprecation")
	@Test
	public final void calculateTheWeights28(){
		BigDecimal[] weights = {new BigDecimal("0.7818"), new BigDecimal("1.2180")};
		assertEquals(weights, newSquare.calculateWeights(new BigDecimal("0.40"),new BigDecimal("0.70")));
	}
	
	@Test (expected = IllegalArgumentException.class)
	public final void calculateWeightsIllegalHumidity(){
		newSquare.calculateWeights(null,new BigDecimal("0.30"));
	}
	
	@Test (expected = IllegalArgumentException.class)
	public final void setIllegalWeightConstant(){
		PlainSquare.setWeightConstant(null);
	}
	
	@Test (expected = IllegalArgumentException.class)
	public final void setIllegalWeightConstantBigger(){
		PlainSquare.setWeightConstant(new BigDecimal("0.50"));
	}
	
	@Test (expected = IllegalArgumentException.class)
	public final void setIllegalWeightConstantSmaller(){
		PlainSquare.setWeightConstant(new BigDecimal("0.00"));
	}
	
	@Test 
	public final void setlegalWeightConstant(){
		PlainSquare.setWeightConstant(new BigDecimal("0.30"));
		assertEquals(new BigDecimal("0.30"),newSquare.getWeightConstant());
	}
	
	@Test (expected = IllegalArgumentException.class)
	public final void illegalMerge(){
		newSquare.mergeWith(null,Directions.East);
	}
	
	@Test (expected = IllegalArgumentException.class)
	public final void illegalMergeDirection(){
		newSquare.setBorder(Directions.East,new Wall());
		newSquare.mergeWith(mergeSquare,Directions.East);
	}
	
	@Test
	public final void mergesWith(){
		newSquare.setTemperature(50,Temperature.CELCIUS);
		newSquare.setHumidity(new BigDecimal("0.20"));
		mergeSquare.setTemperature(100,Temperature.CELCIUS);
		mergeSquare.setHumidity(new BigDecimal("0.60"));
		Square[] squares = {newSquare, mergeSquare};
		newSquare.mergesWith(squares);
		assertEquals(85, newSquare.getTemperature(),0);
		assertEquals(new BigDecimal("0.40"), newSquare.getHumidity());
		assertEquals(85, mergeSquare.getTemperature(),0);
		assertEquals(new BigDecimal("0.40"), mergeSquare.getHumidity());
	}
	
	@Test
	public void getInhabitabilityLegalCase() {
		newSquare.setHeatDamageParameters(35, 15);
		Square anotherSquare = new PlainSquare(150, new BigDecimal("0.5901"),null);
		try {
			assertEquals(-2.86,anotherSquare.getInhabitability(),0);
		} catch (IllegalHeatDamageOverflowException e) {
			e.printStackTrace();
		}
		
		
	}
	
	//Op zich kan er nooit een overflow komen want bij het instellen van de parameters
	//	voor die heat damage wordt al rekening gehouden met de opgelegde
	//	beperkingen qua temperatuur
	//@Test (expected = IllegalHeatDamageOverflowException.class)
	//public void getInhabitabilityIllLegalCase() {
	//	try {
	//	newSquare.setMinMaxTemperature(0, Integer.MAX_VALUE);
	//	newSquare.setTemperature(Integer.MAX_VALUE, Temperature.CELCIUS);
	//	newSquare.getInhabitability();
	//	} catch (Exception e) {
	//		
	//		e.printStackTrace();
	//	}
		
	@Test 
	public final void getBordersByDirectionNorth(){
		Wall wall = new Wall();
		newSquare.setBorder(Directions.North,wall);
		assertEquals(wall, newSquare.getBorderByDirection(Directions.North));
	}
	
	@Test 
	public final void getBordersByDirectionsouth(){
		Wall wall = new Wall();
		newSquare.setBorder(Directions.South,wall);
		assertEquals(wall, newSquare.getBorderByDirection(Directions.South));
	}
	
	@Test 
	public final void getBordersByDirectioneast(){
		Wall wall = new Wall(new Door());
		newSquare.setBorder(Directions.East,wall);
		assertEquals(wall, newSquare.getBorderByDirection(Directions.East));
	}
	
	@Test
	public final void newSquareWithBorders(){
		Directions [] borders =  {Directions.Ceiling, Directions.East, Directions.North};
		Square borderSquare = new PlainSquare(0, new BigDecimal("0.5"), borders);
		assertEquals(3,borderSquare.hasNumberBorders());
		assertTrue(borderSquare.hasBorder(Directions.East));
	}

	@Test 
	public final void setThreeDoors(){
		Wall wall1 = new Wall(new Door());
		Wall wall2 = new Wall(new Door());
		Wall wall3 = new Wall(new Door());
		newSquare.setBorder(Directions.East, wall1);
		newSquare.setBorder(Directions.West, wall2);
		newSquare.setBorder(Directions.North, wall3);
		assertEquals(3, newSquare.hasNumberOfDoors());
	}
	
	
	@Test
	public final void setFourDoors(){
		Wall wall1 = new Wall(new Door());
		Wall wall2 = new Wall(new Door());
		Wall wall3 = new Wall(new Door());
		Wall wall4 = new Wall(new Door());
		newSquare.setBorder(Directions.East, wall1);
		newSquare.setBorder(Directions.West, wall2);
		newSquare.setBorder(Directions.North, wall3);
		newSquare.setBorder(Directions.South, wall4);
		assertEquals(3, newSquare.hasNumberOfDoors());
		assertFalse(newSquare.hasBorder(Directions.South));
	}
	
	@Test
	public final void setFloorDoor(){
		Wall wall = new Wall(new Door());
		newSquare.setBorder(Directions.Floor, wall);
		assertEquals(0, newSquare.hasNumberOfDoors());
		assertFalse(newSquare.getBorderByDirection(Directions.Floor).hasDoor());
		assertTrue(newSquare.hasBorder(Directions.Floor));
	}
	
	@Test
	public final void terminateSquare(){
		Door door = new Door();
		Wall wall = new Wall(door);
		newSquare.setBorder(Directions.East, wall);
		newSquare.terminate();
		assertTrue(door.isTerminated());
		assertTrue(wall.isTerminated());
		assertTrue(newSquare.isTerminated());
	}
	
	@Test
	public final void newSquareWithoutBorder(){
		assertTrue(newSquare.hasBorder(Directions.Floor));
		assertEquals(1,newSquare.hasNumberBorders());
	}
	
	@Test
	public final void newSquareWithNullBorder(){
		Square square = new PlainSquare(50, new BigDecimal("0.20"), null);
		assertTrue(square.hasBorder(Directions.Floor));
		assertEquals(1,newSquare.hasNumberBorders());
	}
	
	@Test
	public final void newSquareWithNullBorders(){
		Directions [] borders = {};
		Square square = new PlainSquare(50, new BigDecimal("0.20"), borders);
		assertTrue(square.hasBorder(Directions.Floor));
		assertEquals(1,newSquare.hasNumberBorders());
		
	}
	
	
	
	
}
	
	


